// 1.4.3 函数-函数参数-引用调用
/**
 * C++ 函数
 * 函数是一组一起执行一个任务的语句。每个 C++ 程序都至少有一个函数，即主函数 main() ，所有简单的程序都可以定义其他额外的函数。
 * 您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的，但在逻辑上，划分通常是根据每个函数执行一个特定的任务来进行的。
 * 函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。 
 * C++ 标准库提供了大量的程序可以调用的内置函数。例如，函数 strcat() 用来连接两个字符串，函数 memcpy() 用来复制内存到另一个位置。
 * 函数还有很多叫法，比如方法、子例程或程序，等等。
 * 
 * ---------------------
 * 函数参数
 * 如果函数要使用参数，则必须声明接受参数值的变量。这些变量称为函数的形式参数。
 * 形式参数就像函数内的其他局部变量，在进入函数时被创建，退出函数时被销毁。
 * 当调用函数时，有三种向函数传递参数的方式：
 * 1.传值调用
 * 该方法把参数的实际值赋值给函数的形式参数。在这种情况下，修改函数内的形式参数对实际参数没有影响。
 * 2.指针调用
 * 该方法把参数的地址赋值给形式参数。在函数内，该地址用于访问调用中要用到的实际参数。这意味着，修改形式参数会影响实际参数。
 * 3.引用调用
 * 该方法把参数的引用赋值给形式参数。在函数内，该引用用于访问调用中要用到的实际参数。这意味着，修改形式参数会影响实际参数。
 * 
 * 默认情况下，C++ 使用传值调用来传递参数。一般来说，这意味着函数内的代码不能改变用于调用函数的参数。之前提到的实例，调用 max() 函数时，使用了相同的方法。
 * 
 * ~~~~~~~~~~~~~~~
 * 引用调用
 * 向函数传递参数的引用调用方法，把引用的地址复制给形式参数。在函数内，该引用用于访问调用中要用到的实际参数。这意味着，修改形式参数会影响实际参数。
 * 按引用传递值，参数引用被传递给函数，就像传递其他值给函数一样。因此相应地，在下面的函数 swap() 中，您需要声明函数参数为引用类型，该函数用于交换参数所指向的两个整数变量的值。
*/
#include <iostream>
// void swap(int &, int &); // 函数声明
// void swap(int &a, int &b); // 函数声明
void swap(int &c, int &d); // 函数声明
// void swap(int a, int b); // 报错 多个重载匹配；注释了不保存，调用时就声明了一个，另一个在下面，不影响

int main(void)
{
  int a = 1;
  int b = 2;
  swap(a, b);

  std::cout << "--调用后--"
            << "\n"
            << "a : " << a << "\n"
            << "b : " << b << std::endl;
  // 上面的实例表明了，虽然在函数内改变了 a 和 b 的值，但是实际上 a 和 b 的值没有发生变化。
  printf("---------end-----------");
  return 0;
}

// 函数定义
/**
 * 交换
*/
void swap(int &a, int &b)
{
  std::cout << "调void swap(int &a, int &b)" << std::endl;
  std::cout << "--调用前--"
            << "\n"
            << "a : " << a << "\n"
            << "b : " << b << std::endl;
  // int temp;
  // temp = a; // 保存地址a的值
  // a = b;
  // b = temp;

  // 不用中间变量实现交换数字
  // a = a + b;
  // b = a - b; // a + b - b = a
  // a = a - b; // a + b - a = b

  // 用异或运算符实现交换
  // 一个数与其本身异或等于 0，0 与一个数异或不改变该数。
  // a ^ x ^ x = a 一个数 异或 同一个数两次是它本身

  a = a ^ b;
  b = a ^ b; // a ^ b ^ b = a
  a = a ^ b; // a ^ b ^ a = b

  // std::cout << "a : " << a << "\n"
  //           << "b : " << b << std::endl;
  return;
}

void swap(int a, int b)
{
  std::cout << "调void swap(int a, int b)" << std::endl;
  // int temp;
  // temp = a;
  // a = b;
  // b = temp;

  // 不用中间变量实现交换数字
  // a = a + b;
  // b = a - b; // a + b - b = a
  // a = a - b; // a + b - a = b

  // 用异或运算符实现交换
  // 一个数与其本身异或等于 0，0 与一个数异或不改变该数。
  // a ^ x ^ x = a 一个数 异或 同一个数两次是它本身

  a = a ^ b;
  b = a ^ b; // a ^ b ^ b = a
  a = a ^ b; // a ^ b ^ a = b
  std::cout << "a : " << a << "\n"
            << "b : " << b << std::endl;
  return;
}
